/**
 * Copyright 2019 Anthony Trinh
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package ch.qos.logback.classic.control;

import java.util.HashMap;
import java.util.Map;

import ch.qos.logback.classic.Level;
import ch.qos.logback.core.CoreConstants;

/**
 * This logger context quite optimized for logger retrieval.
 * 
 * <p>It uses a single loggerMap where the key is the logger name and the value
 * is the logger.
 * 
 * <p>This approach acts a lower limit for what is achievable for low memory
 * usage as well as low creation/retrieval times. However, this simplicity also
 * results in slow effective level evaluation, the most frequently exercised
 * part of the API.
 * 
 * <p>This class is expected to contain correct results, and serve to verify
 * the correctness of a more sophisticated implementation.
 * 
 * @author ceki
 */
public class ControlLoggerContext {

  private ControlLogger root;
  //
  // Hashtable loggerMap = new Hashtable();
  Map<String, ControlLogger> loggerMap = new HashMap<String, ControlLogger>();

  public ControlLoggerContext() {
    this.root = new ControlLogger("root", null);
    this.root.setLevel(Level.DEBUG);
  }

  /**
   * Return this contexts root logger
   * 
   * @return
   */
  public ControlLogger getRootLogger() {
    return root;
  }

  public ControlLogger exists(String name) {
    if (name == null) {
      throw new IllegalArgumentException("name parameter cannot be null");
    }

    synchronized (loggerMap) {
      return (ControlLogger) loggerMap.get(name);
    }
  }

  public final ControlLogger getLogger(String name) {
    if (name == null) {
      throw new IllegalArgumentException("name parameter cannot be null");
    }

    synchronized (loggerMap) {
      ControlLogger cl = (ControlLogger) loggerMap.get(name);
      if (cl != null) {
        return cl;
      }
      ControlLogger parent = this.root;

      int i = 0;
      while (true) {
        i = name.indexOf(CoreConstants.DOT, i);
        if (i == -1) {
          // System.out.println("FINAL-Creating logger named [" + name + "] with
          // parent " + parent.getName());
          cl = new ControlLogger(name, parent);
          loggerMap.put(name, cl);
          return cl;
        } else {
          String parentName = name.substring(0, i);
          ControlLogger p = (ControlLogger) loggerMap.get(parentName);
          if (p == null) {
            // System.out.println("INTERMEDIARY-Creating logger [" + parentName
            // + "] with parent " + parent.getName());
            p = new ControlLogger(parentName, parent);
            loggerMap.put(parentName, p);
          }
          parent = p;
        }
        // make i move past the last found dot.
        i++;
      }
    }
  }

  public Map<String, ControlLogger> getLoggerMap() {
    return loggerMap;
  }
}
